package com.common.dingding.service;

import com.common.dingding.config.DingTalkConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 钉钉服务类
 * 处理钉钉企业内部应用免登相关的业务逻辑
 */
@Service
public class DingTalkService {

    @Autowired
    private DingTalkConfig dingTalkConfig;

    @Autowired
    private RestTemplate restTemplate;

    // 缓存accessToken，避免频繁请求
    private static final ConcurrentHashMap<String, AccessTokenInfo> accessTokenCache = new ConcurrentHashMap<>();
    
    // AccessToken信息类，包含token和过期时间
    private static class AccessTokenInfo {
        private String token;
        private long expireTimeMillis;
        
        public AccessTokenInfo(String token, long expireTimeMillis) {
            this.token = token;
            this.expireTimeMillis = expireTimeMillis;
        }
        
        public String getToken() {
            return token;
        }
        
        public boolean isExpired() {
            return System.currentTimeMillis() > expireTimeMillis;
        }
    }

    /**
     * 通过免登授权码获取用户信息（企业内部应用）
     * @param code 免登授权码
     * @return 用户信息
     */
    public Map<String, Object> getUserInfoByAuthCode(String code) {
        try {
            // 获取accessToken
            String accessToken = getAccessToken();

//            JdtBaseAPI.getAccessToken(dingTalkConfig.getAppKey(),dingTalkConfig.getAppSecret());
            // 构建获取用户信息的请求URL
            String userInfoUrl = "https://oapi.dingtalk.com/user/getuserinfo?access_token=" + accessToken + "&code=" + code;
            
            // 发送请求获取用户userId
            Map<String, Object> response = restTemplate.getForObject(userInfoUrl, Map.class);
            
            if (response != null && "0".equals(response.get("errcode").toString())) {
                String userId = response.get("userid").toString();
                
                // 根据userId获取详细用户信息
                return getUserDetailById(userId, accessToken);
            } else {
                throw new RuntimeException("获取用户userId失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            throw new RuntimeException("获取用户信息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 根据userId获取用户详细信息
     * @param userId 用户的钉钉ID
     * @param accessToken 访问令牌
     * @return 用户详细信息
     */
    public Map<String, Object> getUserDetailById(String userId, String accessToken) {
        String url = "https://oapi.dingtalk.com/user/get?access_token=" + accessToken + "&userid=" + userId;
        Map<String, Object> response = restTemplate.getForObject(url, Map.class);
        
        if (response != null && "0".equals(response.get("errcode").toString())) {
            // 构建用户信息，添加来源标识
            Map<String, Object> userInfo = new HashMap<>(response);
            userInfo.put("userSource", "dingtalk");
            return userInfo;
        } else {
            throw new RuntimeException("获取用户详细信息失败: " + (response != null ? response.get("errmsg") : "未知错误"));
        }
    }

    /**
     * 获取accessToken（企业内部应用）
     * @return accessToken
     */
    private String getAccessToken() {
        // 检查缓存中是否存在有效的accessToken
        AccessTokenInfo accessTokenInfo = accessTokenCache.get("accessToken");
        if (accessTokenInfo != null && !accessTokenInfo.isExpired()) {
            return accessTokenInfo.getToken();
        }
        
        // 缓存不存在或已过期，重新获取
        synchronized (this) {
            // 双重检查锁定，避免并发问题
            accessTokenInfo = accessTokenCache.get("accessToken");
            if (accessTokenInfo != null && !accessTokenInfo.isExpired()) {
                return accessTokenInfo.getToken();
            }
            
            // 新版获取accessToken接口
            String url = "https://api.dingtalk.com/v1.0/oauth2/accessToken";
            
            // 构建请求体
            Map<String, String> requestBody = new HashMap<>();
            requestBody.put("appKey", dingTalkConfig.getAppKey());
            requestBody.put("appSecret", dingTalkConfig.getAppSecret());
            
            // 发送POST请求获取accessToken
            Map<String, Object> response = restTemplate.postForObject(url, requestBody, Map.class);
            
            if (response != null && response.get("accessToken") != null) {
                String accessToken = response.get("accessToken").toString();
                // 从响应中获取过期时间（新版返回的是毫秒数）
                long expireInMillis = Long.parseLong(response.get("expireIn").toString());
                // 计算过期时间，提前10分钟过期（10分钟 = 600000毫秒）
                long expireTimeMillis = System.currentTimeMillis() + expireInMillis - 600000;
                
                // 更新缓存
                accessTokenCache.put("accessToken", new AccessTokenInfo(accessToken, expireTimeMillis));
                return accessToken;
            } else {
                throw new RuntimeException("获取accessToken失败: " + (response != null ? response.get("message") : "未知错误"));
            }
        }
    }


    /**
     * 获取用户的组织信息
     * @param userId 用户ID
     * @return 用户组织信息
     */
    public Map<String, Object> getUserOrgId(String userId) {
        try {
            String accessToken = getAccessToken();
            // 构建获取用户信息的请求URL
            String url = "https://oapi.dingtalk.com/user/get?access_token=" + accessToken + "&userid=" + userId;

            Map<String, Object> response = restTemplate.getForObject(url, Map.class);

            if (response != null && "0".equals(response.get("errcode").toString())) {
                Map<String, Object> orgInfo = new HashMap<>();
                orgInfo.put("orgId", response.get("department"));
                orgInfo.put("orgName", response.get("department_name"));
                return orgInfo;
            } else {
                throw new RuntimeException("获取用户组织信息失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            throw new RuntimeException("获取用户组织信息失败: " + e.getMessage(), e);
        }
    }

    /**
     * 获取组织的详细信息
     * @param orgId 组织ID
     * @return 组织详细信息
     */
    public Map<String, Object> getOrganizationDetail(String orgId) {
        try {
            String accessToken = getAccessToken();
            // 构建获取组织信息的请求URL
            String url = "https://oapi.dingtalk.com/department/get?access_token=" + accessToken + "&id=" + orgId;
            
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            
            if (response != null && "0".equals(response.get("errcode").toString())) {
                return response;
            } else {
                throw new RuntimeException("获取组织详细信息失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            throw new RuntimeException("获取组织详细信息失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 获取组织下的所有用户
     * @param orgId 组织ID
     * @return 组织下的用户列表
     */
    public List<Map<String, Object>> getUsersByOrganization(String orgId) {
        try {
            String accessToken = getAccessToken();
            // 构建获取组织用户的请求URL
            String url = "https://oapi.dingtalk.com/user/list?access_token=" + accessToken + "&department_id=" + orgId + "&offset=0&size=100";
            
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            
            if (response != null && "0".equals(response.get("errcode").toString())) {
                return (List<Map<String, Object>>) response.get("userlist");
            } else {
                throw new RuntimeException("获取组织用户失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            throw new RuntimeException("获取组织用户失败: " + e.getMessage(), e);
        }
    }
    
    /**
     * 获取用户可以管理的用户ID列表
     * @param userId 当前用户ID
     * @return 可以管理的用户ID列表
     */
    public List<Map<String, Object>> getManageableUserIds(String userId,boolean isWorkshopScheduler,boolean isScheduler) {
        try {
            Map<String, Object> userOrg = getUserOrgId(userId);
            List<Map<String, Object>> users = new ArrayList<>();
            
            if (isWorkshopScheduler || isScheduler) {
                String orgId = userOrg.get("orgId").toString();
                // 处理orgId格式，提取纯数字ID
                if(orgId.startsWith("[")) {
                    // 如果是列表格式，先尝试转换为List对象
                    if(userOrg.get("orgId") instanceof List) {
                        List<Integer> orgIdTemp = (List<Integer>)userOrg.get("orgId");
                        orgId = orgIdTemp.get(0).toString();
                    } else {
                        // 如果是字符串格式的列表，提取第一个ID
                        orgId = orgId.replaceAll("\\[|\\]", "").trim();
                        if(orgId.contains(",")) {
                            orgId = orgId.split(",")[0].trim();
                        }
                    }
                }
                if (isWorkshopScheduler) {
                    // 车间排班管理员可以管理本车间（所处组织）的所有人
                    users = getUsersByOrganization(orgId);

                } else if (isScheduler) {
                    // 排班管理员可以管理所处组织结构的上一层组织的所有人
                    Map<String, Object> orgDetail = getOrganizationDetail(orgId);
                    String parentOrgId = orgDetail.get("parentid").toString();
                    
                    // 同样处理parentOrgId的格式
                    if(parentOrgId.startsWith("[")) {
                        parentOrgId = parentOrgId.replaceAll("\\[|\\]", "").trim();
                        if(parentOrgId.contains(",")) {
                            parentOrgId = parentOrgId.split(",")[0].trim();
                        }
                    }
                    
                    users = getUsersByOrganization(parentOrgId);
                }
            }
            
            return users;
        } catch (Exception e) {
            throw new RuntimeException("获取可管理用户列表失败: " + e.getMessage(), e);
        }
    }


    /**
     * 获取用户可以管理的用户列表和组织机构列表
     * @param userId 当前用户ID
     * @return 可以管理的用户ID列表
     */
    public List<Map<String, Object>> getManageableUserIdsAndOrg(String userId,boolean isWorkshopScheduler,boolean isScheduler) {
        try {
            Map<String, Object> userOrg = getUserOrgId(userId);
            List<Map<String, Object>> users = new ArrayList<>();
            List<Map<String, Object>> OrgList = new ArrayList<>();
            List<Map<String, Object>> resList = new ArrayList<>();
            if (isWorkshopScheduler || isScheduler) {
                String orgId = userOrg.get("orgId").toString();
                // 处理orgId格式，提取纯数字ID
                if(orgId.startsWith("[")) {
                    // 如果是列表格式，先尝试转换为List对象
                    if(userOrg.get("orgId") instanceof List) {
                        List<Integer> orgIdTemp = (List<Integer>)userOrg.get("orgId");
                        orgId = orgIdTemp.get(0).toString();
                    } else {
                        // 如果是字符串格式的列表，提取第一个ID
                        orgId = orgId.replaceAll("\\[|\\]", "").trim();
                        if(orgId.contains(",")) {
                            orgId = orgId.split(",")[0].trim();
                        }
                    }
                }
                if (isWorkshopScheduler) {
                    // 车间排班管理员可以管理本车间（所处组织）的所有人
                    users = getUsersByOrganization(orgId);
                    OrgList = getOrganizationsByParentId(orgId);

                } else if (isScheduler) {
                    // 排班管理员可以管理所处组织结构的上一层组织的所有人
                    Map<String, Object> orgDetail = getOrganizationDetail(orgId);
                    String parentOrgId = orgDetail.get("parentid").toString();

                    // 同样处理parentOrgId的格式
                    if(parentOrgId.startsWith("[")) {
                        parentOrgId = parentOrgId.replaceAll("\\[|\\]", "").trim();
                        if(parentOrgId.contains(",")) {
                            parentOrgId = parentOrgId.split(",")[0].trim();
                        }
                    }

                    users = getUsersByOrganization(parentOrgId);
                    OrgList = getOrganizationsByParentId(parentOrgId);
                }
            }
            users.addAll(OrgList);
            return users;
        } catch (Exception e) {
            throw new RuntimeException("获取可管理用户及组织机构列表失败: " + e.getMessage(), e);
        }
    }


    /**
     * 获取指定组织机构下的子组织机构(不需要用递归往下找)
     * @param orgId 父组织机构ID
     * @return 子组织机构列表
     */
    public List<Map<String, Object>> getOrganizationsByParentId(String orgId) {
        try {
            String accessToken = getAccessToken();
            // 构建获取组织机构列表的请求URL，使用钉钉department/list接口
            String url = "https://oapi.dingtalk.com/department/list?access_token=" + accessToken + "&id=" + orgId + "&fetch_child=0";
            
            // 发送请求获取组织机构列表
            Map<String, Object> response = restTemplate.getForObject(url, Map.class);
            
            if (response != null && "0".equals(response.get("errcode").toString())) {
                // 直接返回部门列表
                return (List<Map<String, Object>>) response.get("department");
            } else {
                throw new RuntimeException("获取组织机构列表失败: " + (response != null ? response.get("errmsg") : "未知错误"));
            }
        } catch (Exception e) {
            throw new RuntimeException("获取组织机构列表失败: " + e.getMessage(), e);
        }
    }
}